package io.kiki.sba.registry.server.metadata.resource;

import com.codahale.metrics.Gauge;
import com.codahale.metrics.MetricRegistry;
import io.kiki.sba.registry.common.model.Node.NodeType;
import io.kiki.sba.registry.common.model.console.PersistenceData;
import io.kiki.sba.registry.common.model.constants.ValueConstants;
import io.kiki.sba.registry.metrics.ReporterUtils;
import io.kiki.sba.registry.server.metadata.metadataServer.impl.DefaultMetaServerManager;
import io.kiki.sba.registry.server.metadata.provide.data.ProvideDataService;
import io.kiki.sba.registry.server.metadata.resource.filter.LeaderAwareRestController;
import io.kiki.sba.registry.store.api.DBResponse;
import io.kiki.sba.registry.store.api.OperationStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import javax.annotation.PostConstruct;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import java.util.HashMap;
import java.util.Map;


@Path("digest")
@LeaderAwareRestController
public class MetaDigestResource {

    private static final Logger logger = LoggerFactory.getLogger(MetaDigestResource.class);


    @Autowired
    private DefaultMetaServerManager metaServerManager;

    @Autowired
    private ProvideDataService provideDataService;

    private static String getEntityData(DBResponse<PersistenceData> resp) {
        if (resp != null && resp.getEntity() != null) {
            return resp.getEntity().getData();
        }
        return null;
    }

    @PostConstruct
    public void init() {
        MetricRegistry metrics = new MetricRegistry();
        metrics.register("metaNodeList", (Gauge<Map>) () -> getRegisterNodeByType(NodeType.central_control.name()));
        metrics.register("dataNodeList", (Gauge<Map>) () -> getRegisterNodeByType(NodeType.data_store.name()));
        metrics.register("sessionNodeList", (Gauge<Map>) () -> getRegisterNodeByType(NodeType.client_interface.name()));
        metrics.register("pushSwitch", (Gauge<Map>) () -> getPushSwitch());
        ReporterUtils.startSlf4jReporter(60, metrics);
    }

    @GET
    @Path("{type}/node/query")
    @Produces(MediaType.APPLICATION_JSON)
    public Map getRegisterNodeByType(@PathParam("type") String type) {
        try {
            return metaServerManager.getSummary(NodeType.valueOf(type.toUpperCase())).getNodes();
        } catch (Exception e) {
            logger.error("Fail get Register Node By Type:{}", type, e);
            throw new RuntimeException("Fail get Register Node By Type:" + type, e);
        }
    }

    @GET
    @Path("pushSwitch")
    @Produces(MediaType.APPLICATION_JSON)
    public Map<String, String> getPushSwitch() {
        Map<String, String> resultMap = new HashMap<>(1);
        resultMap.putAll(globalPushSwitch());
        resultMap.putAll(grayPushSwitch());
        return resultMap;
    }

    public Map<String, String> globalPushSwitch() {
        DBResponse<PersistenceData> ret = provideDataService.queryProvideData(ValueConstants.STOP_PUSH_DATA_SWITCH_DATA_ID);

        Map<String, String> resultMap = new HashMap<>(1);
        if (ret.getOperationStatus() == OperationStatus.success) {
            String result = getEntityData(ret);
            if (result != null && !result.isEmpty()) {
                resultMap.put("stopPush", result);
            } else {
                resultMap.put("stopPush", result);
                resultMap.put("msg", "data is empty");
            }
        } else
            if (ret.getOperationStatus() == OperationStatus.notfound) {
                resultMap.put("msg", "(global push switch)OperationStatus is NOTFOUND");
            }
        logger.info("[getPushSwitch] {}", resultMap);
        return resultMap;
    }

    public Map<String, String> grayPushSwitch() {
        DBResponse<PersistenceData> ret = provideDataService.queryProvideData(ValueConstants.PUSH_SWITCH_GRAY_OPEN_DATA_ID);

        Map<String, String> resultMap = new HashMap<>(1);
        if (ret.getOperationStatus() == OperationStatus.success) {
            String result = getEntityData(ret);
            if (result != null && !result.isEmpty()) {
                resultMap.put("grayPushSwitch", result);
            } else {
                resultMap.put("grayPushSwitch", result);
                resultMap.put("gray push switch msg", "data is empty");
            }
        } else
            if (ret.getOperationStatus() == OperationStatus.notfound) {
                resultMap.put("gray push switch msg", "OperationStatus is NOTFOUND");
            }
        logger.info("[getGrayPushSwitch] {}", resultMap);
        return resultMap;
    }


    protected MetaDigestResource setMetaServerManager(DefaultMetaServerManager metaServerManager) {
        this.metaServerManager = metaServerManager;
        return this;
    }


    protected MetaDigestResource setProvideDataService(ProvideDataService provideDataService) {
        this.provideDataService = provideDataService;
        return this;
    }
}
